﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Windows.Forms;
using System.Data.SqlClient;
using Model;
using Common;
using Controller;
using System.Text.RegularExpressions;


namespace CodeFactory
{
    public partial class TableSelector : Form
    {

        private TableSelectorBO _tsBO;
        public TableSelectorBO TsBO
        {
            get 
            {
                if (_tsBO == null)
                    _tsBO = FactoryControllerBO.CurrentFA.CreateTableSelectorBOInstace();
                return _tsBO; 
            }
           
        }
      

        #region 初始化

        public TableSelector()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="list">数据库中的表名的列表</param>
        /// <param name="conStr">上一步的连接字符串，用于手动输入命令</param>
        public TableSelector(string conStr,List<string> list,MainStudio _mainStudio)
        {
            InitializeComponent();
            list.ForEach(item => cblTableSelect.Items.Add(item));
            connectStr = conStr;
            sortList = list;
            txtConfigName.Text = String.Format("{0}.{1}.dbo", conStr.Split(';')[0].Substring(12).Trim(), conStr.Split(';')[1].Substring(16).Trim());
            mainStudio = _mainStudio;
        }

        #endregion

     
        #region 私有字段
     
        private List<string> sortList;
        
        private string splitString ="--";//2个
       
        private enumSortDirection sortDirection = enumSortDirection.ASC;

        private MainStudio mainStudio;

        #endregion

        
        #region 属性
        public string connectStr { get; set; }
        #endregion

        
        #region 其他控件事件

        private void cblTableSelect_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            string tableName = cblTableSelect.Items[e.Index].ToString();

            if (e.NewValue == CheckState.Checked)
            {
                //将取出的字段别名命名成跟FieldType中的对应属性名相同，便于调用（自己制定的规则）
                string cmdStr = @"SELECT sc.name       AS FieldName, 
                                         st.name       AS DataType,
                                         sp.value      AS [Description],   
                                         sc.isnullable AS IsNullable, 
                                         sc.length     AS FieldLength
                                    FROM sys.syscolumns sc
                              INNER JOIN sys.systypes   st
                                      ON sc.xusertype = st.xusertype
                               Left JOIN sys.extended_properties sp
                                      ON sc.id=sp.major_id 
                                         AND sc.colid=sp.minor_id 
                                   WHERE sc.id = OBJECT_ID('{0}')";
                cmdStr = String.Format(cmdStr, tableName);
                List<eBuildFieldInfo> list = GetFieldsByTableFromDb(connectStr, cmdStr, tableName);
                TreeNode parentNode = new TreeNode(tableName);
                list.ForEach(ft => parentNode.Nodes.Add(new TreeNode(ft.FieldName + splitString + ft.DataType + splitString + ft.Description)));
                treeSelectFields.Nodes.Add(parentNode);
                treeSelectFields.CollapseAll();
            }
            else
            {
                foreach (TreeNode node in treeSelectFields.Nodes)
                {
                    if (node.Text.Equals(tableName))
                    {
                        treeSelectFields.Nodes.Remove(node);
                    }
                }
                treeSelectFields.CollapseAll();
            }


        }


        private void treeSelectFields_AfterCheck(object sender, TreeViewEventArgs e)
        {
            if (e.Action != TreeViewAction.Unknown)
            {
               SetNodeCheckStatus(e.Node, e.Node.Checked);
            }
        }
        

        #endregion

        
        #region 私有方法

        /// <summary>
        /// 处数选中父节点全选子节点
        /// 选中子节点时选中父节点
        /// </summary>
        /// <param name="tn"></param>
        /// <param name="tnChecked"></param>
        private void SetNodeCheckStatus(TreeNode tn, bool tnChecked)
        {
            if (tn.Parent == null) //点击的是根节点，将子节点状态设成跟其一致
            {
                foreach (TreeNode childTN in tn.Nodes)
                {
                    childTN.Checked = tnChecked;
                }
            }
            else   //点击的是子节点
            {
                int Count = 0;
                foreach (TreeNode childTN in tn.Parent.Nodes)
                {
                    if (childTN.Checked)
                    {
                        Count++;
                    }
                }
                tn.Parent.Checked = Count > 1 ? true : tnChecked;
            }

        }

        /// <summary>
        /// 获取已选择的字段列表
        /// </summary>
        /// <returns></returns>
        private List<exFieldInfo> GetXmlFieldInfoFromTree()
        {
            try
            {
                List<exFieldInfo> list = new List<exFieldInfo>();
                List<exFieldInfoChild> listChild;
                exFieldInfo ot;
                foreach (TreeNode tn in treeSelectFields.Nodes)
                {
                    if (!tn.Checked)
                        continue;

                    ot = new exFieldInfo();
                    listChild = new List<exFieldInfoChild>();
                    ot.TableName = tn.Text;
                    foreach (TreeNode childTN in tn.Nodes)
                    {
                        if (childTN.Checked)
                        { 
                            exFieldInfoChild xfic = new exFieldInfoChild
                            {   
                                FieldName = Regex.Split(childTN.Text,splitString,RegexOptions.IgnoreCase)[0].Trim(),
                                FieldType = Regex.Split(childTN.Text, splitString, RegexOptions.IgnoreCase)[1].Trim(),
                                Description = Regex.Split(childTN.Text,splitString,RegexOptions.IgnoreCase)[2].Trim()
                                /*分隔符有2个"-"*/
                            };
                            listChild.Add(xfic);
                        }
                    }
                    ot.FieldInfoList = listChild;
                    list.Add(ot);
                }
                return list;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 获取总体配置
        /// </summary>
        /// <param name="IsQuery">是不是从SQL语句保存</param>
        /// <returns></returns>
        private exMenuConfigChild GetMenuConfig(bool IsQuery)
        {
            exMenuConfigChild mcc = new exMenuConfigChild
            {
                ConfigName = txtConfigName.Text.Trim(),
                ConnectString = connectStr,
                DataBase = connectStr.Split(';')[1].Substring(16).Trim(),
                HasASPNET = chkAsp.Checked,
                HasDevExpree = chkDev.Checked,
                HasDevLayout = chkDevlayout.Checked,
                HasMicrosoft = chkMS.Checked,
                HasWinForm = chkWinform.Checked,
                HasWPF = chkWpf.Checked,
                IsBuildFieldTable = chkSelectFD.Checked,
                IsBuildTable = chkSelectTB.Checked,
                IsQueryType = IsQuery,
                QueryString = IsQuery ? txtSQL.Text.Trim() : ""
            };
            return mcc;
        }

        /// <summary>
        /// 获取一个表所有的字段信息
        /// </summary>
        /// <param name="conStr">连接字符串</param>
        /// <param name="sqlStr">SQL命令</param>
        /// <param name="tableName">表名</param>
        /// <returns></returns>
        private List<eBuildFieldInfo> GetFieldsByTableFromDb(string conStr, string sqlStr, string tableName)
        {
            List<eBuildFieldInfo> list = new List<eBuildFieldInfo>();
            try
            {
                list=TsBO.GetFieldsByTableFromDb(conStr, sqlStr, tableName);
            }
            catch
            {
                MessageBox.Show("连接出错或无连接,请检查各参数");
            }
            return list;
        
        }

        #endregion

        
        #region 按钮事件
        private void tsBtnSort_Click(object sender, EventArgs e)
        {
            try
            {
                cblTableSelect.Items.Clear();
                SortHelper.SortList(sortDirection.ToString(), sortList);
                sortList.ForEach(item => cblTableSelect.Items.Add(item));
                sortDirection = sortDirection == enumSortDirection.ASC ? enumSortDirection.DESC : enumSortDirection.ASC;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void tsBtnExpand_Click(object sender, EventArgs e)
        {
            treeSelectFields.ExpandAll();
        }

        private void tsBtnCollapse_Click(object sender, EventArgs e)
        {
            treeSelectFields.CollapseAll();
        }

        private void tsBtnAllSelect_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < cblTableSelect.Items.Count; i++)
            {
                cblTableSelect.SetItemCheckState(i, CheckState.Checked);
            }
        }
                                           
        private void tsBtnNoSelect_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < cblTableSelect.Items.Count; i++)
            {
                cblTableSelect.SetItemCheckState(i, CheckState.Unchecked);
            }
        }

        private void btnSaveSel_Click(object sender, EventArgs e)
        {
            try
            {
                exMenuConfigChild mcc = GetMenuConfig(false);
                List<exFieldInfo> list = GetXmlFieldInfoFromTree();
                if (TsBO.SaveMenuConfigToXml(mcc) == 1)
                {
                    MessageBox.Show("已经存在相同配置名！");
                    return;
                }
                if (TsBO.SaveBuildInfoToXml(mcc.ConfigName, list) == 1)
                {
                    MessageBox.Show("已经存在相同配置名！");
                    return;
                }
                Owner.Close();
                this.Close();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        private void btnSelectTB_Click(object sender, EventArgs e)
        {
            try
            {
                exMenuConfigChild mcc = GetMenuConfig(false);
                List<exFieldInfo> list = GetXmlFieldInfoFromTree();
                if (TsBO.SaveMenuConfigToXml(mcc) == 1)
                {
                    MessageBox.Show("已经存在相同配置名！");
                    return;
                }
                if (TsBO.SaveBuildInfoToXml(mcc.ConfigName, list) == 1)
                {
                    MessageBox.Show("已经存在相同配置名！");
                    return;
                }
                Owner.Close();
                this.Close();
                using (ControlSelector cs = new ControlSelector(mcc.ConfigName,mainStudio))
                {
                    cs.ShowDialog();
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #endregion

        private void tsBtnAllSelect2_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < treeSelectFields.Nodes.Count; i++)
            {
                CheckBoxCheck(treeSelectFields.Nodes[i], true);
            }
        }

        private void CheckBoxCheck(TreeNode tn, bool IsChecked)
        {
            tn.Checked = IsChecked;
            if (tn.Nodes.Count > 0)
            {
                for (int i = 0; i < tn.Nodes.Count; i++)
                {
                    CheckBoxCheck(tn.Nodes[i], IsChecked);
                }
            }
        }


        private void tsBtnNoSelect2_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < treeSelectFields.Nodes.Count; i++)
            {
                CheckBoxCheck(treeSelectFields.Nodes[i], false);
            }
        }

       


   }
}
